home *** CD-ROM | disk | FTP | other *** search
- /*-------------------------------------------------------------------------------------
- *
- * Simple Sample PowerTalk Application Framework
- *
- * ©1991-1993 Apple Computer
- *
- -------------------------------------------------------------------------------------*/
- /*
- * draw.window.c -- window class instantiation/dispatching
- *
- * change history:
- *
- * SJF 08/23/93 1.0f1 update to final headers, fix comments
- * SJF 04/21/93 1.0b2 update to b2
- * SJF 03/01/93 1.0b1 added digital signatures
- * SJF 02/09/93 1.0b1 update to b1
- * SJF 10/13/92 1.0d4 update to a11
- * SJF 09/09/92 1.0d3 update to a9
- * SJF 05/07/92 1.0d2 update to a6
- * SJF 11/06/91 1.0d1 initial coding
- *
- */
-
- #ifndef __TYPES__
- #include <Types.h>
- #endif
-
- #ifndef __QUICKDRAW__
- #include <QuickDraw.h>
- #endif
-
- #ifndef __WINDOWS__
- #include <Windows.h>
- #endif
-
- #ifndef __MENUS__
- #include <Menus.h>
- #endif
-
- #ifndef __FILES__
- #include <Files.h>
- #endif
-
- #ifndef __SCRIPT__
- #include <Script.h>
- #endif
-
- #ifndef __ERRORS__
- #include <Errors.h>
- #endif
-
- #ifndef __FOLDERS__
- #include <Folders.h>
- #endif
-
- #ifdef THINK_C
- #include <BDC.h> //workaround for problem with Think's packages.h
- #endif
-
- #ifndef __PACKAGES__
- #include <Packages.h>
- #endif
-
- #ifndef __OCESTANDARDMAIL__
- #include <OCEStandardMail.h>
- #endif
-
- #ifndef __RESOURCES__
- #include <Resources.h>
- #endif
-
- #include "const.h"
- #include "strconst.h"
- #include "mytypes.h"
- #include "globals.h"
- #include "utils.h"
- #include "windowstuff.h"
- #include "mymenus.h"
- #include "digisig.h"
- #include "base.window.h"
- #include "windutils.h"
-
- #include "draw.window.h"
-
- #define kLineSlop 5
- #define kSlop 2
- #define kAnchorWidth 2
-
- /* instantiate a new draw window */
-
- WindowPtr DrawMakeWindow(Rect *wRect,StringPtr title,Boolean visible,short wdefProc,
- Boolean goAwayFlag)
- {
- WInfoPtr infoPtr;
- WindowPtr theWindow;
- char hState;
-
- theWindow = BaseMakeWindow(wRect,title,visible,wdefProc,goAwayFlag);
- SetWindowKind(theWindow,kDrawWindow);
-
- infoPtr = BeginWindowAccess(theWindow,&hState);
-
- SetDrawMethods(infoPtr);
-
- // set other window information
- infoPtr->data = nil;
- infoPtr->otherData[kDSIGData] = nil;
-
- // make scroll bars
- MakeScrollBars(theWindow,infoPtr);
-
- EndWindowAccess(theWindow,hState);
-
- return theWindow;
- }
-
-
- /* set up the method pointers for the drawing window class (may be called when a mailer
- gets added/removed
- */
- void SetDrawMethods(WInfoPtr infoPtr)
- {
- infoPtr->m_idle = BaseIdleWindow;
- infoPtr->m_fixCursor = DrawFixCursorWindow;
- infoPtr->m_activate = DrawActivateWindow;
- infoPtr->m_deactivate = DrawDeactivateWindow;
- infoPtr->m_update = DrawUpdateWindow;
- infoPtr->m_key = BaseKeyWindow;
- infoPtr->m_resize = DrawResizeWindow;
- infoPtr->m_click = DrawClickWindow;
- infoPtr->m_destroy = DrawDestroyWindow;
- infoPtr->m_undo = DrawUndoWindow;
- infoPtr->m_cut = BaseCutWindow;
- infoPtr->m_copy = BaseCopyWindow;
- infoPtr->m_paste = BasePasteWindow;
- infoPtr->m_clear = BaseClearWindow;
- infoPtr->m_print = DrawPrintWindow;
- infoPtr->m_pageSetup = DrawPageSetupWindow;
- infoPtr->m_save = DrawSaveWindow;
- infoPtr->m_load = DrawLoadWindow;
- infoPtr->m_event = BaseEventWindow;
- infoPtr->m_ctrlHit = DrawHitControlWindow;
- infoPtr->m_selectAll = DrawSelectAllWindow;
- infoPtr->m_group = DrawGroupWindow;
- infoPtr->m_unGroup = DrawUnGroupWindow;
- }
-
-
- /* handle mouse-moved events for draw window */
-
- void *DrawFixCursorWindow(WindowPtr window,WInfoPtr infoPtr,void *data)
- {
- RgnHandle returnRgn;
- unsigned long *crsrData;
- RgnHandle arrowRgn,pencilRgn;
- Point offsetPt,mousePt;
- GrafPtr savePort;
- Rect drawRect;
-
- GetPort(&savePort);
- SetPort(window);
-
- crsrData = (unsigned long *)data;
- returnRgn = (RgnHandle)crsrData[1];
- mousePt = *(Point *)&crsrData[0];
- arrowRgn = NewRgn();
- pencilRgn = NewRgn();
-
- drawRect = window->portRect;
- drawRect.bottom -= 15;
- drawRect.right -= 15;
-
- SetRectRgn(arrowRgn,-32768,-32768,32767,32767);
- RectRgn(pencilRgn,&drawRect);
- SetPt(&offsetPt,0,0);
- LocalToGlobal(&offsetPt);
- OffsetRgn(pencilRgn,offsetPt.h,offsetPt.v);
- DiffRgn(arrowRgn,pencilRgn,arrowRgn);
-
- if (PtInRgn(mousePt,arrowRgn)) {
- CopyRgn(arrowRgn,returnRgn);
- SetCursor(&qd.arrow);
- }
- else if (PtInRgn(mousePt,pencilRgn)) {
- CopyRgn(pencilRgn,returnRgn);
- if (gCurrentShape!=kSelectShape)
- SetCursor(&gPencilCursor);
- else
- SetCursor(&qd.arrow);
- }
-
-
- DisposeRgn(arrowRgn);
- DisposeRgn(pencilRgn);
- SetPort(savePort);
-
- return BaseFixCursorWindow(window,infoPtr,data);
- }
-
-
- /* deallocate any memory associated with the draw window class */
-
- void *DrawDestroyWindow(WindowPtr window,WInfoPtr infoPtr,void *data)
- {
- ShapeListPtr shapeList,prevShape;
- OSErr err;
-
- DSIGCloseFile(infoPtr);
-
- if (infoPtr->fRefNum) {
- err = FSClose(infoPtr->fRefNum);
- if (err!=noErr)
- DoError(err);
- infoPtr->fRefNum = 0;
- }
-
- if (infoPtr->resRefNum) {
- CloseResFile(infoPtr->resRefNum);
- err = ResError();
- if (err!=noErr)
- DoError(err);
- infoPtr->resRefNum = 0;
- }
-
- shapeList = (ShapeListPtr) infoPtr->data;
- while (shapeList) {
- prevShape = shapeList;
- shapeList = shapeList->next;
- DisposPtrChk(prevShape);
- }
-
- DisposeControl(VSCROLL);
- DisposeControl(HSCROLL);
-
- return BaseDestroyWindow(window,infoPtr,data);
- }
-
-
- /* handle undo for draw window */
-
- void *DrawUndoWindow(WindowPtr window,WInfoPtr infoPtr,void *data)
- {
- #pragma unused (data)
- if (!gCanUndo || window!=gUndoCommand.window) {
- DoError(kInternalError);
- return nil;
- }
-
- if (gHasUndo) { // we should redo
- AddShape(gUndoCommand.theShape.shapeType,gUndoCommand.theShape.anchor,
- gUndoCommand.theShape.destination,nil,(ShapeListPtr *)&infoPtr->data,false);
- InvalShapeArea(window,infoPtr,(ShapeListPtr)infoPtr->data);
- gHasUndo = false;
- }
- else {
- RemoveTopShape(window,infoPtr);
- gHasUndo = true;
- }
-
- SetupAppUndo();
- return nil;
- }
-
-
- /* handle activate events for draw window */
-
- void *DrawActivateWindow(WindowPtr window,WInfoPtr infoPtr,void *data)
- {
- MenuHandle theMenu;
-
- DisableAllMenus();
-
- theMenu = GetMHandle(kFileMenu);
- EnableAllMenuItems(theMenu);
- if (!infoPtr->changed)
- DisableItem(theMenu,kSaveItem);
-
- /* only enable mail menu if we have Standard Mail available */
-
- if (gHasStandardMail) {
- theMenu = GetMHandle(kMailMenu);
- EnableAllMenuItems(theMenu);
- DisableItem(theMenu,kSendItem);
- DisableItem(theMenu,kReplyItem);
- DisableItem(theMenu,kReplyToAllItem);
- DisableItem(theMenu,kForwardItem);
- DisableItem(theMenu,kTagLetterItem);
- }
-
- FixDrawMenus(infoPtr);
-
- gMenusDirty = true;
-
- HiliteControl(VSCROLL,0);
- HiliteControl(HSCROLL,0);
-
- return BaseActivateWindow(window,infoPtr,data);
- }
-
-
- /* handle deactivate events for draw window */
-
- void *DrawDeactivateWindow(WindowPtr window,WInfoPtr infoPtr,void *data)
- {
- HiliteControl(VSCROLL,254);
- HiliteControl(HSCROLL,254);
-
- return BaseDeactivateWindow(window,infoPtr,data);
- }
-
-
- /* handle mouse click in content for draw window */
-
- void *DrawClickWindow(WindowPtr window,WInfoPtr infoPtr,void *data)
- {
- GrafPtr savePort;
- RgnHandle saveRgn,windowRgn;
- MenuHandle theMenu;
- Boolean changed;
-
- changed = false;
-
- GetPort(&savePort);
- SetPort(window);
-
- windowRgn = GetScrollersRgn(&window->portRect);
-
- saveRgn = NewRgn();
- GetClip(saveRgn);
- DiffRgn(saveRgn,windowRgn,windowRgn);
- SetClip(windowRgn);
-
- if (gCurrentShape==kSelectShape) {
- changed = WarpExistingShape(window,infoPtr,((EventRecord *)data)->where,
- (((EventRecord *)data)->modifiers & shiftKey)!=0);
- if (changed)
- ClearAppUndo();
- }
- else {
- EnterNewShape(window,infoPtr,((EventRecord *)data)->where);
- changed = true;
- }
-
- SetClip(saveRgn);
- DisposeRgn(saveRgn);
- DisposeRgn(windowRgn);
- SetPort(savePort);
-
- FixDrawMenus(infoPtr);
- theMenu = GetMHandle(kFileMenu); // now we've changed, so the user can save
- EnableItem(theMenu,kSaveItem);
-
- infoPtr->changed |= changed;
- return nil;
- }
-
-
- /* handle update events for draw window */
-
- void *DrawUpdateWindow(WindowPtr window,WInfoPtr infoPtr,void *data)
- {
- RgnHandle saveRgn,windowRgn;
- Point *scrollPos,offsetPos;
-
- scrollPos = (Point*)&infoPtr->otherData[kViewOffset];
- offsetPos.h = infoPtr->leftIndent - scrollPos->h;
- offsetPos.v = infoPtr->topIndent - scrollPos->v;
-
- saveRgn = NewRgn();
- windowRgn = GetScrollersRgn(&window->portRect);
-
- GetClip(saveRgn);
- DiffRgn(saveRgn,windowRgn,windowRgn);
- SetClip(windowRgn);
-
- DrawAllShapes(infoPtr,offsetPos);
-
- SetClip(saveRgn);
- DisposeRgn(saveRgn);
- DisposeRgn(windowRgn);
-
- UpdtControl(window,window->visRgn);
-
- return BaseUpdateWindow(window,infoPtr,data);
- }
-
-
- /* handle window resize for draw window */
-
- void *DrawResizeWindow(WindowPtr window,WInfoPtr infoPtr,void *data)
- {
- #pragma unused (infoPtr)
- Rect *oldSize,gbRect;
-
- oldSize = (Rect *)data;
- gbRect = *oldSize;
- gbRect.top = gbRect.bottom - kGrowBoxWidth;
- gbRect.left = gbRect.right - kGrowBoxWidth;
- EraseRect(&gbRect);
-
- MoveScrollBars(window);
-
- gbRect = window->portRect;
- gbRect.top = gbRect.bottom - kGrowBoxWidth;
- gbRect.left = gbRect.right - kGrowBoxWidth;
- ValidRect(&gbRect);
- MyDrawGrowIcon(window);
-
- return nil;
- }
-
-
- /* handle print for draw window */
-
- void *DrawPrintWindow(WindowPtr window,WInfoPtr infoPtr,void *data)
- {
- #pragma unused (window,data)
- Boolean shouldContinue;
- TPPrPort thePrPort;
- TPrStatus theStatus;
- Point zeroOffset = {0,0};
-
- // open print driver
-
- PrOpen();
- if (PrError()!=noErr) {
- DoError(PrError());
- return nil;
- }
-
- // display print dialog
-
- SetCursor(&qd.arrow);
- shouldContinue = PrJobDialog(infoPtr->printRecord);
- if (PrError()!=noErr) {
- DoError(PrError());
- return nil;
- }
- if (!shouldContinue)
- return nil;
-
- // init printing grafport
-
- thePrPort = PrOpenDoc(infoPtr->printRecord,nil,nil);
- if (PrError()==noErr) {
- PrOpenPage(thePrPort,nil);
- if (PrError()==noErr)
- DrawAllShapes(infoPtr,zeroOffset);
- PrClosePage(thePrPort);
- }
- PrCloseDoc(thePrPort);
-
- if ((((TPPrint)*(infoPtr->printRecord))->prJob.bJDocLoop==bSpoolLoop) && (PrError() == noErr))
- PrPicFile(infoPtr->printRecord, nil, nil, nil, &theStatus);
-
- // close print driver
-
- PrClose();
-
- return nil;
- }
-
-
- /* handle page setup for draw window */
-
- void *DrawPageSetupWindow(WindowPtr window,WInfoPtr infoPtr,void *data)
- {
- Boolean changed;
-
- changed = CheckPageSize(window,infoPtr);
- if (!changed)
- ReCalcScrollBars(window,infoPtr);
-
- return BasePageSetupWindow(window,infoPtr,data);
- }
-
-
- /* handle save for draw window */
-
- void *DrawSaveWindow(WindowPtr window,WInfoPtr infoPtr,void *data)
- {
- OSErr err;
- SMPSaveType saveHow;
- short fRefNum,resRefNum;
-
- saveHow = (SMPSaveType)data;
-
- // handle save as
-
- if (saveHow==kSMPSaveAs) {
-
- // create the new file, deleting any existing file, as per user's std file request
-
- err = FSpCreate(&infoPtr->fileSpec,kAppCreator,kDrawingType,smRoman);
- if (err==dupFNErr) {
- FSpDelete(&infoPtr->fileSpec);
- err = FSpCreate(&infoPtr->fileSpec,kAppCreator,kDrawingType,smRoman);
- }
- if (err!=noErr) {
- DoError(err);
- return nil;
- }
- FSpCreateResFile(&infoPtr->fileSpec,kAppCreator,kDrawingType,smRoman);
- err = ResError();
- if (err!=noErr) {
- FSpDelete(&infoPtr->fileSpec);
- DoError(err);
- return nil;
- }
-
- // open the new file (data fork)
-
- err = FSpOpenDF(&infoPtr->fileSpec,fsRdWrPerm,&fRefNum);
- if (err!=noErr) {
- FSpDelete(&infoPtr->fileSpec);
- DoError(err);
- return nil;
- }
-
- // open the new file (resource fork)
-
- resRefNum = FSpOpenResFile(&infoPtr->fileSpec,fsRdWrPerm);
- err = ResError();
- if (err!=noErr) {
- FSClose(fRefNum);
- FSpDelete(&infoPtr->fileSpec);
- DoError(err);
- return nil;
- }
-
- // close the old file, if it exists
-
- if (infoPtr->fRefNum)
- FSClose(infoPtr->fRefNum);
-
- // store the new fRefNum into the document data structure
-
- infoPtr->fRefNum = fRefNum;
- }
- else
- resRefNum = infoPtr->resRefNum;
-
- // add digital signature information
-
- DSIGSaveFile(infoPtr,resRefNum,false);
- if (saveHow==kSMPSaveAs) {
- if (infoPtr->resRefNum)
- CloseResFile(infoPtr->resRefNum);
- infoPtr->resRefNum = resRefNum;
- }
-
- // save the actual file
-
- err = SaveDrawingToDisk(infoPtr->fRefNum,infoPtr);
- if (err!=noErr) {
- DoError(err);
- return nil;
- }
-
- SetWTitle(window,infoPtr->fileSpec.name);
- return BaseSaveWindow(window,infoPtr,data);
- }
-
-
- /* handle load for draw window */
-
- void *DrawLoadWindow(WindowPtr window,WInfoPtr infoPtr,void *data)
- {
- OSErr err;
- long count;
- short fRefNum,resRefNum;
- FSSpec *fSpec;
- char hState;
-
- fSpec = data;
-
- // open the file. we leave it open for reading and writing the whole time
- // that we need to read stuff out of it.
-
- err = FSpOpenDF(fSpec,fsRdWrPerm,&fRefNum); // we leave the file open
- if (err!=noErr) {
- DoError(err);
- return nil;
- }
- infoPtr->fRefNum = fRefNum;
- resRefNum = FSpOpenResFile(fSpec,fsRdWrPerm);
- err = ResError();
- if (err!=noErr) {
- FSClose(fRefNum);
- DoError(err);
- return nil;
- }
- infoPtr->resRefNum = resRefNum;
-
- // read print record
-
- count = sizeof(TPrint);
- hState = HGetState((Handle)infoPtr->printRecord);
- HLock((Handle)infoPtr->printRecord);
- err = FSRead(fRefNum,&count,*(infoPtr->printRecord));
- HSetState((Handle)infoPtr->printRecord,hState);
- if (err!=noErr) {
- DoError(err);
- return nil;
- }
-
- // read shape information
-
- LoadShapesFromDisk(fRefNum,(ShapeListPtr *)&infoPtr->data);
-
- // do digital signature stuff
-
- DSIGOpenFile(infoPtr);
-
- BaseLoadWindow(window,infoPtr,data);
- }
-
-
- /* handle control hit (in scroll bars) for draw window */
-
- void *DrawHitControlWindow(WindowPtr window,WInfoPtr infoPtr,void *data)
- {
- ControlHitMessage *msg;
- short newValue,oldValue;
- Point mousePos;
-
- msg = (ControlHitMessage *)data;
- mousePos = msg->ev->where;
- GlobalToLocal(&mousePos);
-
- switch (msg->part) {
- case inPageUp:
- case inPageDown:
- TrackControl(msg->control,mousePos,(ProcPtr)ScrollActionProc);
- break;
- case inUpButton:
- case inDownButton:
- TrackControl(msg->control,mousePos,(ProcPtr)ScrollActionProc);
- break;
- case inThumb:
- oldValue = GetCtlValue(msg->control);
- if (TrackControl(msg->control,mousePos,nil)) {
- newValue = GetCtlValue(msg->control);
- if (oldValue!=newValue) {
- if (msg->control==(ControlHandle)VSCROLL)
- MoveGraphics(window,infoPtr,0,newValue-oldValue);
- else
- MoveGraphics(window,infoPtr,newValue-oldValue,0);
- }
- }
- break;
- }
-
- return nil;
- }
-
-
- /* handle select all for draw window */
-
- void *DrawSelectAllWindow(WindowPtr window,WInfoPtr infoPtr,void *data)
- {
- #pragma unused (data)
- ShapeListPtr shapeList;
-
- for (shapeList=infoPtr->data; shapeList!=nil; shapeList=shapeList->next) {
- shapeList->selected = true;
- InvalShapeArea(window,infoPtr,shapeList);
- }
-
- FixDrawMenus(infoPtr);
- return nil;
- }
-
-
- /* handle group shapes for draw window */
-
- void *DrawGroupWindow(WindowPtr window,WInfoPtr infoPtr,void *data)
- {
- ShapeListPtr shapeList,prevShape,selectedShape;
- ShapeListPtr groupList;
- Point anchor,destination,emptyPt = {0,0};
-
- // put all selected shapes into groupList, pulling them out of shapeList
-
- groupList = nil;
- shapeList = infoPtr->data;
- prevShape = nil;
- while (shapeList!=nil) {
- if (shapeList->selected) {
- selectedShape = shapeList;
- selectedShape->selected = false;
- if (prevShape)
- prevShape->next = selectedShape->next;
- else
- infoPtr->data = shapeList->next;
- shapeList = shapeList->next;
- selectedShape->next = groupList;
- groupList = selectedShape;
-
- }
- else {
- prevShape = shapeList;
- shapeList = shapeList->next;
- }
- }
-
- GetGroupBounds(groupList,&anchor,&destination);
- shapeList = AddShape(kBeginGroupTag,anchor,destination,groupList,
- (ShapeListPtr *)&infoPtr->data,false);
- shapeList->selected = true;
- InvalShapeArea(window,infoPtr,shapeList);
- ClearAppUndo();
- FixDrawMenus(infoPtr);
-
- return BaseGroupWindow(window,infoPtr,data);
- }
-
-
- /* handle ungroup shapes for draw window */
-
- void *DrawUnGroupWindow(WindowPtr window,WInfoPtr infoPtr,void *data)
- {
- ShapeListPtr shapeList,prevShape,selectedShape;
- ShapeListPtr ungroupShapes;
-
- // put all group shapes into ungroupShapes, pulling them out of shapeList
-
- ungroupShapes = nil;
- shapeList = infoPtr->data;
- prevShape = nil;
- while (shapeList!=nil) {
- if (shapeList->selected && shapeList->shapeType==kBeginGroupTag) {
- selectedShape = shapeList;
- selectedShape->selected = false;
- if (prevShape)
- prevShape->next = selectedShape->next;
- else
- infoPtr->data = shapeList->next;
- shapeList = shapeList->next;
- selectedShape->next = ungroupShapes;
- ungroupShapes = selectedShape;
-
- }
- else {
- prevShape = shapeList;
- shapeList = shapeList->next;
- }
- }
-
- // add all of the sub-group shapes into the shape list
-
- while (ungroupShapes!=nil) {
- InvalShapeArea(window,infoPtr,ungroupShapes);
-
- shapeList = ungroupShapes->subList;
- while (shapeList!=nil) {
- selectedShape = shapeList;
- selectedShape->selected = true;
- shapeList = shapeList->next;
- selectedShape->next = infoPtr->data;
- infoPtr->data = selectedShape;
- }
-
- shapeList = ungroupShapes;
- if (shapeList->isSigned) {
- shapeList->digSig->shouldDelete = true; // invalidate the group obj digital signature
- shapeList->digSig->shape = nil;
- }
- ungroupShapes = ungroupShapes->next;
- DisposPtrChk(shapeList);
- }
- ClearAppUndo();
- FixDrawMenus(infoPtr);
-
- return BaseUnGroupWindow(window,infoPtr,data);
- }
-
-
- /*------- non window-class stuff ---------*/
-
-
- /* let the user enter a new shape */
-
- void EnterNewShape(WindowPtr window,WInfoPtr infoPtr,Point where)
- {
- Point anchor,destination,offsetPos;
- Point emptyPt = {0,0};
- Point *scrollPos;
- ShapeListPtr shapeList;
-
- scrollPos = (Point *)&infoPtr->otherData[kViewOffset];
- anchor = where;
- GlobalToLocal(&anchor);
- destination = anchor;
-
- RubberBandShape(gCurrentShape,anchor,&destination,emptyPt);
- DrawCurrentShape(gCurrentShape,anchor,destination,emptyPt);
-
- offsetPos.h = scrollPos->h-infoPtr->leftIndent;
- offsetPos.v = scrollPos->v-infoPtr->topIndent;
-
- anchor.h += offsetPos.h;
- anchor.v += offsetPos.v;
- destination.h += offsetPos.h;
- destination.v += offsetPos.v;
-
- for (shapeList = infoPtr->data; shapeList!=nil; shapeList = shapeList->next) {
- if (shapeList->selected) {
- shapeList->selected = false;
- EraseAnchorPoints(shapeList,offsetPos);
- }
- }
-
- AddShape(gCurrentShape,anchor,destination,nil,
- (ShapeListPtr *)&infoPtr->data,false);
- AddShapeUndo(gCurrentShape,anchor,destination,window,infoPtr);
- }
-
-
- /* do the rubber band thing with either a new or existing shape */
-
- void RubberBandShape(short shapeType,Point anchor,Point *retDestination,Point offset)
- {
- RgnHandle prevRgn,newRgn,invRgn,opDiffRgn,swapRgn,innerRgn;
- Point destination,newDest;
-
- destination = *retDestination;
-
- PenNormal();
- switch (shapeType) {
- case kLineShape:
- PenMode(patXor);
- DrawCurrentShape(shapeType,anchor,destination,offset);
- while (WaitMouseUp()) {
- GetMouse(&newDest);
- newDest.h -= offset.h;
- newDest.v -= offset.v;
- if (!EqualPt(newDest,destination)) {
- DrawCurrentShape(shapeType,anchor,destination,offset);
- destination = newDest;
- DrawCurrentShape(shapeType,anchor,destination,offset);
- }
- }
- break;
- default:
- prevRgn = NewRgn();
- newRgn = NewRgn();
- invRgn = NewRgn();
- opDiffRgn = NewRgn();
- innerRgn = NewRgn();
-
- OpenRgn();
- DrawCurrentShape(shapeType,anchor,destination,offset);
- CloseRgn(prevRgn);
- CopyRgn(prevRgn,innerRgn);
- InsetRgn(innerRgn,1,1);
- DiffRgn(prevRgn,innerRgn,prevRgn);
-
- InvertRgn(prevRgn);
- EmptyRgn(newRgn);
-
- while (WaitMouseUp()) {
- GetMouse(&newDest);
- newDest.h -= offset.h;
- newDest.v -= offset.v;
- if (!EqualPt(newDest,destination)) {
- destination = newDest;
-
- OpenRgn();
- DrawCurrentShape(shapeType,anchor,destination,offset);
- CloseRgn(newRgn);
- CopyRgn(newRgn,innerRgn);
- InsetRgn(innerRgn,1,1);
- DiffRgn(newRgn,innerRgn,newRgn);
-
- DiffRgn(prevRgn,newRgn,invRgn);
- DiffRgn(newRgn,prevRgn,opDiffRgn);
- UnionRgn(invRgn,opDiffRgn,invRgn);
- InvertRgn(invRgn);
- swapRgn = prevRgn;
- prevRgn = newRgn;
- newRgn = swapRgn;
- }
- }
- InvertRgn(prevRgn);
- DisposeRgn(prevRgn);
- DisposeRgn(newRgn);
- DisposeRgn(invRgn);
- DisposeRgn(opDiffRgn);
- DisposeRgn(innerRgn);
- break;
- }
-
- PenNormal();
- *retDestination = destination;
- }
-
-
- /* select or move or stretch a shape that already exists */
- /* return true if a shape changed */
-
- Boolean WarpExistingShape(WindowPtr window,WInfoPtr infoPtr,Point where,Boolean extendSelection)
- {
- Point *scrollPos,offsetPos;
- ShapeListPtr shapeList,otherList;
- Boolean hitShape,wasSelected,warpedShape,changedShape;
- Point newDest,oldDest,firstDest;
-
- warpedShape = false;
- hitShape = false;
- wasSelected = false;
- changedShape = false;
-
- // determine offsets due to scrolling, indent, global-local changes
-
- scrollPos = (Point *)&infoPtr->otherData[kViewOffset];
- offsetPos.h = infoPtr->leftIndent - scrollPos->h;
- offsetPos.v = infoPtr->topIndent - scrollPos->v;
- GlobalToLocal(&where);
-
- // do hit testing
-
- shapeList = infoPtr->data;
- while (shapeList && !hitShape) {
- hitShape = CheckHitShape(window,infoPtr,offsetPos,where,shapeList,&warpedShape);
- if (!hitShape)
- shapeList = shapeList->next;
- if (warpedShape)
- changedShape = true;
- }
-
-
- // mark shape selected
-
- if (hitShape) {
-
- if (shapeList->selected==false) {
- wasSelected = false;
- shapeList->selected = true;
- }
- else
- wasSelected = true;
- }
-
- // if shift wasn't held, unselect all other objects
-
- if ((extendSelection==false) && ((warpedShape==true)||(hitShape==false)||(wasSelected==false))) {
- for (otherList = infoPtr->data; otherList!=nil; otherList = otherList->next) {
- if (otherList->selected && (!hitShape||(otherList!=shapeList)||!shapeList->selected)) {
- otherList->selected = false;
- EraseAnchorPoints(otherList,offsetPos);
- }
- }
- }
-
- if (hitShape) {
-
- for (otherList = infoPtr->data; otherList!=nil; otherList = otherList->next) {
- if (otherList->selected) {
- InvalShapeArea(window,infoPtr,otherList);
- }
- }
-
- // do shape moving stuff
-
- GetMouse(&oldDest);
- newDest = oldDest;
- while (WaitMouseUp() && EqualPt(newDest,oldDest))
- GetMouse(&newDest);
- if (!EqualPt(newDest,oldDest)) {
-
- // draw shape in gray, since we're going to move it
-
- for (otherList = infoPtr->data; otherList!=nil; otherList = otherList->next) {
- if (otherList->selected) {
- #ifdef dangerousPattern
- PenPat(qd.gray);
- #else
- PenPat(&qd.gray);
- #endif
- DrawShapeObject(otherList,offsetPos,false);
- #ifdef dangerousPattern
- PenPat(qd.black);
- #else
- PenPat(&qd.black);
- #endif
- PenMode(patXor);
- DrawShapeObject(otherList,offsetPos,false);
- }
- }
-
- // move shape(s) here
-
- GetMouse(&firstDest);
- newDest = firstDest;
- while (WaitMouseUp()) {
- oldDest = newDest;
- GetMouse(&newDest);
- if (!EqualPt(oldDest,newDest)) {
- oldDest.h = offsetPos.h - firstDest.h + oldDest.h;
- oldDest.v = offsetPos.v - firstDest.v + oldDest.v;
- for (otherList = infoPtr->data; otherList!=nil; otherList = otherList->next) {
- if (otherList->selected)
- DrawShapeObject(otherList,oldDest,false);
- }
- oldDest.h = offsetPos.h - firstDest.h + newDest.h;
- oldDest.v = offsetPos.v - firstDest.v + newDest.v;
- for (otherList = infoPtr->data; otherList!=nil; otherList = otherList->next) {
- if (otherList->selected)
- DrawShapeObject(otherList,oldDest,false);
- }
- }
- }
- for (otherList = infoPtr->data; otherList!=nil; otherList = otherList->next) {
- if (otherList->selected) {
- OffsetShape(otherList,newDest.h-firstDest.h,newDest.v-firstDest.v);
- InvalShapeArea(window,infoPtr,otherList);
- }
- }
- changedShape = true;
-
- }
- }
-
- PenNormal();
- return changedShape;
- }
-
-
- /* perform a hit test on the object, returning whether the object was hit or should be warped */
-
- Boolean CheckHitShape(WindowPtr window,WInfoPtr infoPtr,Point offsetPos,Point hitPt,
- ShapeListPtr theShape,Boolean *warp)
- {
- RgnHandle shape,overShape;
- Rect boundBox;
- Boolean hitShape;
- Point anchor,destination;
- float slope,intercept,hitPoint;
- ShapeListPtr groupList;
-
- hitShape = false;
- *warp = false;
- shape = NewRgn();
- overShape = NewRgn();
-
- // check bounding box
-
- if (theShape->anchor.h < theShape->destination.h) {
- boundBox.left = theShape->anchor.h;
- boundBox.right = theShape->destination.h;
- }
- else {
- boundBox.left = theShape->destination.h;
- boundBox.right = theShape->anchor.h;
- }
- if (theShape->anchor.v < theShape->destination.v) {
- boundBox.top = theShape->anchor.v;
- boundBox.bottom = theShape->destination.v;
- }
- else {
- boundBox.top = theShape->destination.v;
- boundBox.bottom = theShape->anchor.v;
- }
- boundBox.top += offsetPos.v;
- boundBox.bottom += offsetPos.v;
- boundBox.left += offsetPos.h;
- boundBox.right += offsetPos.h;
- InsetRect(&boundBox,-kSlop,-kSlop);
-
- // check hit in digital signature button
-
- if (DSIGHitShape(infoPtr,hitPt,offsetPos,theShape))
- hitShape = false;
-
- // check hit in shape area
-
- else if (PtInRect(hitPt,&boundBox)) {
-
- // check hit on group shape
-
- if (theShape->shapeType==kBeginGroupTag) {
- if (CheckHitAnchor(theShape,hitPt,offsetPos,&anchor,&destination))
- hitShape = true;
- else
- for (groupList=theShape->subList; groupList!=nil && hitShape==false;
- groupList=groupList->next) {
- if (CheckHitShape(window,infoPtr,offsetPos,hitPt,groupList,warp))
- hitShape = true;
- }
- }
-
- // check rubber banding (for warping an object)
-
- else if (CheckHitAnchor(theShape,hitPt,offsetPos,&anchor,&destination)) {
- #ifdef dangerousPattern
- PenPat(qd.gray);
- #else
- PenPat(&qd.gray);
- #endif
- DrawShapeObject(theShape,offsetPos,false);
- #ifdef dangerousPattern
- PenPat(qd.black);
- #else
- PenPat(&qd.black);
- #endif
- InvalShapeArea(window,infoPtr,theShape);
- RubberBandShape(theShape->shapeType,anchor,&destination,offsetPos);
- theShape->anchor = anchor;
- theShape->destination = destination;
- InvalShapeArea(window,infoPtr,theShape);
- hitShape = true;
- *warp = true;
- }
-
- // check hit on an object -- line
-
- else if (theShape->shapeType==kLineShape) {
- hitPt.h -= offsetPos.h;
- hitPt.v -= offsetPos.v;
- if (theShape->anchor.h==theShape->destination.h) {
- if ((theShape->anchor.h > hitPt.h-kLineSlop) &&
- (theShape->anchor.h < hitPt.h+kLineSlop))
- hitShape = true;
- }
- else {
- slope = (float)(theShape->anchor.v-theShape->destination.v) /
- (float)(theShape->anchor.h-theShape->destination.h);
- intercept = (float)theShape->anchor.v - (slope * (float)theShape->anchor.h);
- hitPoint = (slope * (float)hitPt.h) + intercept;
- if (((short)hitPoint > (hitPt.v-kLineSlop)) &&
- ((short)hitPoint < (hitPt.v+kLineSlop)))
- hitShape = true;
- else {
- hitPoint = ((float)hitPt.v - intercept) / slope;
- if (((short)hitPoint > (hitPt.h-kLineSlop)) &&
- ((short)hitPoint < (hitPt.h+kLineSlop)))
- hitShape = true;
- }
- }
- }
-
- // check hit on an object -- other
-
- else {
- OpenRgn();
- DrawShapeObject(theShape,offsetPos,false);
- CloseRgn(shape);
- CopyRgn(shape,overShape);
- InsetRgn(shape,kSlop,kSlop);
- InsetRgn(overShape,-kSlop,-kSlop);
- DiffRgn(overShape,shape,overShape);
- if (PtInRgn(hitPt,overShape))
- hitShape = true;
- }
- }
-
- DisposeRgn(shape);
- DisposeRgn(overShape);
- return hitShape;
- }
-
-
- /* draws all the shapes */
-
- void DrawAllShapes(WInfoPtr infoPtr,Point offsetPos)
- {
- ShapeListPtr shapeList;
-
- PenNormal();
- for (shapeList=infoPtr->data; shapeList!=nil; shapeList=shapeList->next) {
- DrawShapeObject(shapeList,offsetPos,true);
- }
- }
-
-
- /* draws the shape from a shape record */
-
- void DrawShapeObject(ShapeListPtr theShape,Point drawOffset,Boolean selected)
- {
- if (theShape->shapeType==kBeginGroupTag) {
- DrawAnchorPoints(theShape,drawOffset,selected ? theShape->selected : false);
- if (selected)
- DSIGDrawSigner(theShape,drawOffset);
- for (theShape = theShape->subList; theShape!=nil; theShape = theShape->next)
- DrawShapeObject(theShape,drawOffset,false);
- }
- else {
- DrawCurrentShape(theShape->shapeType,theShape->anchor,theShape->destination,drawOffset);
- DrawAnchorPoints(theShape,drawOffset,selected ? theShape->selected : false);
- if (selected)
- DSIGDrawSigner(theShape,drawOffset);
- }
- }
-
-
- /* draws the shape from components*/
-
- void DrawCurrentShape(short theShape,Point anchor,Point endPt,Point drawOffset)
- {
- Rect theRect;
- Point emptyPt = {0,0};
-
- anchor.h += drawOffset.h;
- anchor.v += drawOffset.v;
- endPt.h += drawOffset.h;
- endPt.v += drawOffset.v;
-
- // draw the shape
-
- switch (theShape) {
- case kLineShape:
- MoveTo(anchor.h,anchor.v);
- LineTo(endPt.h,endPt.v);
- break;
- case kRectShape:
- SetRect(&theRect,anchor.h,anchor.v,endPt.h,endPt.v);
- FixRect(&theRect);
- FrameRect(&theRect);
- break;
- case kRoundRectShape:
- SetRect(&theRect,anchor.h,anchor.v,endPt.h,endPt.v);
- FixRect(&theRect);
- FrameRoundRect(&theRect,15,15);
- break;
- case kOvalShape:
- SetRect(&theRect,anchor.h,anchor.v,endPt.h,endPt.v);
- FixRect(&theRect);
- FrameOval(&theRect);
- break;
- }
- }
-
- /* draw the anchor points for a shape */
-
- void DrawAnchorPoints(ShapeListPtr theShape,Point drawOffset,Boolean selected)
- {
- Rect theRect;
- Boolean fourAnchors;
- Point anchor,endPt;
-
- anchor = theShape->anchor;
- endPt = theShape->destination;
-
- if (theShape->shapeType==kLineShape)
- fourAnchors = false;
- else
- fourAnchors = true;
-
- anchor.h += drawOffset.h;
- anchor.v += drawOffset.v;
- endPt.h += drawOffset.h;
- endPt.v += drawOffset.v;
-
- SetRect(&theRect,anchor.h-kAnchorWidth,anchor.v-kAnchorWidth,
- anchor.h+kAnchorWidth,anchor.v+kAnchorWidth);
- if (selected)
- #ifdef dangerousPattern
- FillRect(&theRect,qd.black);
- #else
- FillRect(&theRect,&qd.black);
- #endif
- SetRect(&theRect,endPt.h-kAnchorWidth,endPt.v-kAnchorWidth,
- endPt.h+kAnchorWidth,endPt.v+kAnchorWidth);
- if (selected)
- #ifdef dangerousPattern
- FillRect(&theRect,qd.black);
- #else
- FillRect(&theRect,&qd.black);
- #endif
- if (fourAnchors) {
- SetRect(&theRect,anchor.h-kAnchorWidth,endPt.v-kAnchorWidth,
- anchor.h+kAnchorWidth,endPt.v+kAnchorWidth);
- if (selected)
- #ifdef dangerousPattern
- FillRect(&theRect,qd.black);
- #else
- FillRect(&theRect,&qd.black);
- #endif
- SetRect(&theRect,endPt.h-kAnchorWidth,anchor.v-kAnchorWidth,
- endPt.h+kAnchorWidth,anchor.v+kAnchorWidth);
- if (selected)
- #ifdef dangerousPattern
- FillRect(&theRect,qd.black);
- #else
- FillRect(&theRect,&qd.black);
- #endif
- }
- }
-
-
- /* erase the anchor points for a shape */
-
- void EraseAnchorPoints(ShapeListPtr theShape,Point drawOffset)
- {
- Point anchor,endPt;
- Rect theRect;
- Boolean fourAnchors;
-
- if (theShape->shapeType == kLineShape)
- fourAnchors = false;
- else
- fourAnchors = true;
-
- anchor.h = theShape->anchor.h + drawOffset.h;
- anchor.v = theShape->anchor.v + drawOffset.v;
- endPt.h = theShape->destination.h + drawOffset.h;
- endPt.v = theShape->destination.v + drawOffset.v;
-
- SetRect(&theRect,anchor.h-kAnchorWidth,anchor.v-kAnchorWidth,
- anchor.h+kAnchorWidth,anchor.v+kAnchorWidth);
- InvalRect(&theRect);
- SetRect(&theRect,endPt.h-kAnchorWidth,endPt.v-kAnchorWidth,
- endPt.h+kAnchorWidth,endPt.v+kAnchorWidth);
- InvalRect(&theRect);
- if (fourAnchors) {
- SetRect(&theRect,anchor.h-kAnchorWidth,endPt.v-kAnchorWidth,
- anchor.h+kAnchorWidth,endPt.v+kAnchorWidth);
- InvalRect(&theRect);
- SetRect(&theRect,endPt.h-kAnchorWidth,anchor.v-kAnchorWidth,
- endPt.h+kAnchorWidth,anchor.v+kAnchorWidth);
- InvalRect(&theRect);
- }
- }
-
-
- /* see if we hit an anchor point, and if yes, return anchor and destination points */
-
- Boolean CheckHitAnchor(ShapeListPtr theShape,Point hitPt,Point offsetPos,Point *anchor,
- Point *endPt)
- {
- Rect theRect;
- Boolean fourAnchors;
-
- hitPt.h -= offsetPos.h;
- hitPt.v -= offsetPos.v;
-
- if (theShape->selected==false)
- return false;
-
- if (theShape->shapeType == kLineShape)
- fourAnchors = false;
- else
- fourAnchors = true;
-
- *anchor = theShape->anchor;
- *endPt = theShape->destination;
-
- SetRect(&theRect,anchor->h-kAnchorWidth,anchor->v-kAnchorWidth,
- anchor->h+kAnchorWidth,anchor->v+kAnchorWidth);
- if (PtInRect(hitPt,&theRect)) {
- *anchor = theShape->destination;
- *endPt = theShape->anchor;
- return true;
- }
-
- SetRect(&theRect,endPt->h-kAnchorWidth,endPt->v-kAnchorWidth,
- endPt->h+kAnchorWidth,endPt->v+kAnchorWidth);
- if (PtInRect(hitPt,&theRect)) {
- *anchor = theShape->anchor;
- *endPt = theShape->destination;
- return true;
- }
-
- if (fourAnchors) {
-
- SetRect(&theRect,anchor->h-kAnchorWidth,endPt->v-kAnchorWidth,
- anchor->h+kAnchorWidth,endPt->v+kAnchorWidth);
- if (PtInRect(hitPt,&theRect)) {
- anchor->h = theShape->destination.h;
- anchor->v = theShape->anchor.v;
- endPt->h = theShape->anchor.h;
- endPt->v = theShape->destination.v;
- return true;
- }
-
- SetRect(&theRect,endPt->h-kAnchorWidth,anchor->v-kAnchorWidth,
- endPt->h+kAnchorWidth,anchor->v+kAnchorWidth);
- if (PtInRect(hitPt,&theRect)) {
- anchor->h = theShape->anchor.h;
- anchor->v = theShape->destination.v;
- endPt->h = theShape->destination.h;
- endPt->v = theShape->anchor.v;
- return true;
- }
- }
- return false;
- }
-
-
- /* re-orient rectangle so top-left is at top-left */
-
- void FixRect(Rect *rect)
- {
- short pt;
-
- if (rect->left > rect->right) {
- pt = rect->left;
- rect->left = rect->right;
- rect->right = pt;
- }
-
- if (rect->top > rect->bottom) {
- pt = rect->top;
- rect->top = rect->bottom;
- rect->bottom = pt;
- }
- }
-
-
- /* offset shape by delta */
-
- void OffsetShape(ShapeListPtr theShape,short deltaH,short deltaV)
- {
- ShapeListPtr groupList;
-
- if (theShape->shapeType == kBeginGroupTag) {
- for (groupList=theShape->subList; groupList!=nil; groupList=groupList->next)
- OffsetShape(groupList,deltaH,deltaV);
- }
-
- theShape->anchor.h += deltaH;
- theShape->anchor.v += deltaV;
- theShape->destination.h += deltaH;
- theShape->destination.v += deltaV;
- }
-
-
- /* add a shape to the document */
-
- ShapeListPtr AddShape(short currentShape,Point anchor,Point destination,ShapeListPtr subList,
- ShapeListPtr *shapeHead,Boolean addToEnd)
- {
- ShapeListPtr newShape;
-
- newShape = NewPtrChk(sizeof(ShapeList));
- if (MemError()!=noErr) {
- DoError(MemError());
- return nil;
- }
-
- // note: all of this funny business with "addToEnd" is to insure that the shapes are
- // not reversed during the save/load process so that any group digital signatures will still
- // remain valid
-
- if (addToEnd && *shapeHead) {
- (*shapeHead)->next = newShape;
- newShape->next = nil;
- *shapeHead = newShape;
- }
- else {
- newShape->next = *shapeHead;
- *shapeHead = newShape;
- }
-
- newShape->anchor = anchor;
- newShape->destination = destination;
- newShape->shapeType = currentShape;
- newShape->selected = false;
- newShape->isSigned = false;
- newShape->signatureID = 0;
- newShape->subList = subList;
- }
-
-
- /* set up the undo op. we only support undo for adding shapes for now */
-
- void AddShapeUndo(short currentShape,Point anchor,Point destination,WindowPtr window,
- WInfoPtr infoPtr)
- {
- ShapeList newShape;
-
- newShape.anchor = anchor;
- newShape.destination = destination;
- newShape.shapeType = currentShape;
- SetUndoCommand(window,infoPtr,&newShape);
- FixDrawMenus(infoPtr);
- }
-
-
- /* removes the top-most shape from the document (for undo) */
-
- void RemoveTopShape(WindowPtr window,WInfoPtr infoPtr)
- {
- ShapeList *shapeToKill,*shapeList;
-
- shapeList = (ShapeListPtr) infoPtr->data;
- shapeToKill = shapeList;
- InvalShapeArea(window,infoPtr,shapeToKill);
-
- infoPtr->data = shapeList->next;
- DisposPtrChk(shapeToKill);
- }
-
-
- /* forces a redraw of the area a shape occupies in the window (for when it has changed) */
-
- void InvalShapeArea(WindowPtr window,WInfoPtr infoPtr,ShapeList *theShape)
- {
- GrafPtr savePort;
- Rect shapeRect;
- Point *scrollPos;
- RgnHandle shapeRgn,scrollRgn;
-
- GetPort(&savePort);
- SetPort(window);
-
- SetRect(&shapeRect,theShape->anchor.h,theShape->anchor.v,
- theShape->destination.h,theShape->destination.v);
- FixRect(&shapeRect);
-
- scrollPos = (Point *)&infoPtr->otherData[kViewOffset];
- OffsetRect(&shapeRect,infoPtr->leftIndent-scrollPos->h,infoPtr->topIndent-scrollPos->v);
- InsetRect(&shapeRect,-5,-5); // for slop
- shapeRgn = NewRgn();
- scrollRgn = GetScrollersRgn(&window->portRect);
- RectRgn(shapeRgn,&shapeRect);
- DiffRgn(shapeRgn,scrollRgn,shapeRgn);
- InvalRgn(shapeRgn);
- DisposeRgn(shapeRgn);
- DisposeRgn(scrollRgn);
-
- SetPort(savePort);
- }
-
-
- /* see how many shapes are selected */
-
- short CheckShapeSelected(WInfoPtr infoPtr)
- {
- ShapeListPtr shapeList;
- short shapeCount;
-
- shapeCount = 0;
- for (shapeList=infoPtr->data; shapeList!=nil; shapeList=shapeList->next) {
- if (shapeList->selected)
- shapeCount++;
- }
- return shapeCount;
- }
-
-
- /* see if a group is selected */
-
- short CheckGroupSelected(WInfoPtr infoPtr)
- {
- ShapeListPtr shapeList;
-
- for (shapeList=infoPtr->data; shapeList!=nil; shapeList=shapeList->next) {
- if (shapeList->selected && shapeList->shapeType==kBeginGroupTag)
- return true;
- }
- return false;
- }
-
-
- /* get the coordinate bounds of a group of shapes (for signing outline) */
-
- void GetGroupBounds(ShapeListPtr groupList,Point *anchor,Point *destination)
- {
- anchor->h = groupList->anchor.h;
- anchor->v = groupList->anchor.v;
- destination->h = groupList->destination.h;
- destination->v = groupList->destination.v;
-
- while (groupList) {
- if (groupList->anchor.h < anchor->h)
- anchor->h = groupList->anchor.h;
- if (groupList->destination.h < anchor->h)
- anchor->h = groupList->destination.h;
- if (groupList->anchor.v < anchor->v)
- anchor->v = groupList->anchor.v;
- if (groupList->destination.v < anchor->v)
- anchor->v = groupList->destination.v;
- if (groupList->anchor.h > destination->h)
- destination->h = groupList->anchor.h;
- if (groupList->destination.h > destination->h)
- destination->h = groupList->destination.h;
- if (groupList->anchor.v > destination->v)
- destination->v = groupList->anchor.v;
- if (groupList->destination.v > destination->v)
- destination->v = groupList->destination.v;
-
- groupList = groupList->next;
- }
- }
-
-
- /* save our document to a temporary file so we can send it within a letter */
-
- OSErr SaveFileToTemp(WInfoPtr infoPtr,FSSpec *fSpec)
- {
- OSErr err;
- long randNum;
- Str255 randStr;
- short fRefNum,resRefNum;
-
- err = FindFolder(kOnSystemDisk,kTemporaryFolderType,true,&fSpec->vRefNum,&fSpec->parID);
- if (err!=noErr)
- return err;
-
- randNum = (unsigned long) Random();
- NumToString(randNum,randStr);
- pstrcpy(fSpec->name,randStr);
-
- // create the temporary file
-
- err = FSpCreate(fSpec,kAppCreator,kDrawingType,smRoman);
- if (err==dupFNErr) {
- FSpDelete(fSpec);
- err = FSpCreate(fSpec,kAppCreator,kDrawingType,smRoman);
- }
- if (err!=noErr) {
- FSpDelete(fSpec);
- return err;
- }
- FSpCreateResFile(fSpec,kAppCreator,kDrawingType,smRoman);
- err = ResError();
- if (err!=noErr) {
- FSpDelete(fSpec);
- return err;
- }
-
- // open the temporary file
-
- err = FSpOpenDF(fSpec,fsRdWrPerm,&fRefNum);
- if (err!=noErr) {
- FSpDelete(fSpec);
- return err;
- }
- resRefNum = FSpOpenResFile(fSpec,fsRdWrPerm);
- err = ResError();
- if (err!=noErr) {
- FSClose(fRefNum);
- FSpDelete(&infoPtr->fileSpec);
- return err;
- }
-
- // save the digital signature information
-
- DSIGSaveFile(infoPtr,resRefNum,true);
-
- // save the data into the temporary file
-
- err = SaveDrawingToDisk(fRefNum,infoPtr);
-
- // close the file
-
- FSClose(fRefNum);
- CloseResFile(resRefNum);
-
- if (err!=noErr) {
- FSpDelete(fSpec);
- }
-
- return err;
- }
-
-
- /* save our drawing document to an open disk file pointed to by fRefNum */
-
- OSErr SaveDrawingToDisk(short fRefNum,WInfoPtr infoPtr)
- {
- OSErr err;
- ShapeListPtr shapeList;
- long count,totalCount;
- char hState;
-
- // set file position to start of file
-
- err = SetFPos(fRefNum,fsFromStart,0);
- if (err!=noErr)
- return err;
- totalCount = 0;
-
- // write print record
-
- count = sizeof(TPrint);
- hState = HGetState((Handle)infoPtr->printRecord);
- HLock((Handle)infoPtr->printRecord);
- err = FSWrite(fRefNum,&count,*(infoPtr->printRecord));
- totalCount += count;
- HSetState((Handle)infoPtr->printRecord,hState);
- if (err!=noErr)
- return err;
-
- // write shape information
-
- shapeList = infoPtr->data;
- err = SaveShapesToDisk(fRefNum,infoPtr->data,&totalCount);
- if (err!=noErr)
- return err;
-
- // set file length
-
- err = SetEOF(fRefNum,totalCount);
-
- return err;
- }
-
-
- /* save a list of shapes to a disk file pointed to by fRefNum */
- /* may be called recursively for groups */
-
- OSErr SaveShapesToDisk(short fRefNum,ShapeListPtr shapeList,long *totalCount)
- {
- long count;
- OSErr err;
-
- while (shapeList) {
- count = sizeof(ShapeList);
- err = FSWrite(fRefNum,&count,shapeList);
- *totalCount += count;
- if (err!=noErr) {
- return err;
- }
- if (shapeList->shapeType==kBeginGroupTag) {
- err = SaveShapesToDisk(fRefNum,shapeList->subList,totalCount);
- if (err!=noErr)
- return err;
- count = sizeof(ShapeList);
- shapeList->shapeType = kEndGroupTag;
- err = FSWrite(fRefNum,&count,shapeList);
- *totalCount += count;
- shapeList->shapeType = kBeginGroupTag;
- }
-
- shapeList = shapeList->next;
- }
- return err;
- }
-
-
- /* load a list of shapes from a disk file pointed to by fRefNum */
- /* may be called recursively for groups */
-
- OSErr LoadShapesFromDisk(short fRefNum,ShapeListPtr *shapeHead)
- {
- long count;
- OSErr err;
- ShapeList theShape;
- ShapeListPtr newShape,endShape;
-
- endShape = *shapeHead;
-
- do {
- count = sizeof(ShapeList);
- err = FSRead(fRefNum,&count,&theShape);
- if (err==noErr) {
- if (theShape.shapeType==kBeginGroupTag) {
- theShape.subList = nil;
- err = LoadShapesFromDisk(fRefNum,&theShape.subList);
- if (err==noErr) {
- newShape = AddShape(theShape.shapeType,theShape.anchor,theShape.destination,
- theShape.subList,&endShape,true);
- newShape->isSigned = theShape.isSigned;
- newShape->signatureID = theShape.signatureID;
- }
- }
- else if (theShape.shapeType!=kEndGroupTag) {
- newShape = AddShape(theShape.shapeType,theShape.anchor,theShape.destination,
- nil,&endShape,true);
- newShape->isSigned = theShape.isSigned;
- newShape->signatureID = theShape.signatureID;
- }
- if (*shapeHead==nil)
- *shapeHead = endShape;
- }
- } while (err==noErr && theShape.shapeType!=kEndGroupTag);
- return err;
- }
-
-
- /* fix up the drawing menu items when the state of the document has changed */
-
- void FixDrawMenus(WInfoPtr infoPtr)
- {
- MenuHandle theMenu;
-
- FixDrawEditMenu();
-
- theMenu = GetMHandle(kShapesMenu);
- EnableAllMenuItems(theMenu);
- if (CheckShapeSelected(infoPtr)<2)
- DisableItem(theMenu,kGroupItem);
- if (!CheckGroupSelected(infoPtr))
- DisableItem(theMenu,kUngroupItem);
-
- DSIGSetupSignMenu(infoPtr);
-
- gMenusDirty = true;
- }
-
-
- /* fix up the edit menu items when the state of the document has changed */
-
- void FixDrawEditMenu(void)
- {
- MenuHandle theMenu;
-
- theMenu = GetMHandle(kEditMenu);
- EnableAllMenuItems(theMenu);
- if (!SetupAppUndo())
- DisableItem(theMenu,kUndoItem);
- DisableItem(theMenu,kCutItem);
- DisableItem(theMenu,kCopyItem);
- DisableItem(theMenu,kPasteItem);
- DisableItem(theMenu,kClearItem);
- }